/*
 * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include "aes.h"

unsigned char ivec[16] = {0x5a, 0x4e, 0x78, 0x6c, 0x66, 0x68, 0x61, 0x6e,
							0x78, 0x2e, 0x64, 0x61, 0x34, 0x2a, 0x40, 0x50};

unsigned char key16[16] = {0x6d, 0x78, 0x6c, 0x65, 0x63, 0x78, 0x61, 0x73,
							   0x64, 0x6a, 0x6e, 0x66, 0x6f, 0x61, 0x77, 0x7a};

unsigned long AES_cbc_encrypt(int argc, char** argv)
{
	unsigned char inData[1024];
	unsigned char outData[1024];
	char *inPath;
	int len=0, outLen=0;
	AES_KEY aes_ks;

	FILE *infp = NULL;

	if(argc != 1)
		return -1;
	inPath= argv[0];

	if(inPath == NULL)
	{
		return 1;
	}

	 if((infp = fopen(inPath, "rb+"))==NULL)
	{
		return 2;
	}

	 AES_set_encrypt_key(key16, 128, &aes_ks);

	 while(1)
	 {
	 	 memset(inData, 0, sizeof(inData));
	   	 len = fread(inData, 1, sizeof(inData),  (FILE*)infp);
		 if(len <= 0)
		 {
			break;
		 }

		 memset(outData,0,sizeof(outData));

		outLen = CRYPTO_cbc128_encrypt(inData, outData, len, &aes_ks, ivec,
		                      (block128_f) AES_encrypt);
		fseek(infp, (len*(-1)), SEEK_CUR);
		 fwrite(outData, 1, outLen, infp);

	 }
	 fclose(infp);
	return 0;
}

unsigned long AES_cbc_decrypt(int argc, char** argv)
{
	unsigned char inData[1024];
	unsigned char outData[1024];
	int len=0, outLen=0;
	AES_KEY aes_ks;
	char *inPath;
	FILE *infp = NULL;

	if(argc != 1)
		return -1;
	inPath = argv[0];

	if(inPath == NULL)
	{
		return 1;
	}

	 if((infp = fopen(inPath, "rb+"))==NULL)
	{
		return 2;
	}
	 AES_set_decrypt_key(key16, 128, &aes_ks);
	 while(1)
	 {
	   	 len = fread(inData, 1, sizeof(inData),  (FILE*)infp);
		 if(len <= 0)
		 {
			break;
		 }

		memset(outData,0,sizeof(outData));

		outLen = CRYPTO_cbc128_decrypt(inData, outData, len, &aes_ks, ivec,
		                      (block128_f) AES_decrypt);

		fseek(infp, (len*(-1)), SEEK_CUR);
		 fwrite(outData, 1, outLen, infp);
	 }
	 fclose(infp);
	return 0;

}

unsigned long AES_cbc_encrypt_file(const char * inPath, unsigned char * key)
{
	unsigned char ivec[16] = {0x5a, 0x4e, 0x78, 0x6c, 0x66, 0x68, 0x61, 0x6e,
								0x78, 0x2e, 0x64, 0x61, 0x34, 0x2a, 0x40, 0x50};
	unsigned char inData[1024];
	unsigned char outData[1024];
	int len=0, outLen=0;
	AES_KEY aes_ks;

	FILE *infp = NULL;

	if((inPath == NULL) || (key == NULL))
	{
		return 1;
	}

	if((infp = fopen(inPath, "rb+"))==NULL)
	{
		return 2;
	}

	AES_set_encrypt_key(key, 128, &aes_ks);
	while(1)
	{
	 	memset(inData, 0, sizeof(inData));
	   	len = fread(inData, 1, sizeof(inData),  (FILE*)infp);
		if(len <= 0)
		{
			break;
		}

		memset(outData,0,sizeof(outData));
		outLen = CRYPTO_cbc128_encrypt(inData, outData, len, &aes_ks, ivec,
		                      (block128_f) AES_encrypt);
		fseek(infp, (len*(-1)), SEEK_CUR);
		fwrite(outData, 1, outLen, infp);

	}
	fclose(infp);
	return 0;
}

unsigned long AES_cbc_decrypt_file(const char * inPath, unsigned char * key)
{
	unsigned char ivec[16] = {0x5a, 0x4e, 0x78, 0x6c, 0x66, 0x68, 0x61, 0x6e,
								0x78, 0x2e, 0x64, 0x61, 0x34, 0x2a, 0x40, 0x50};
	unsigned char inData[1024];
	unsigned char outData[1024];
	int len=0, outLen=0;
	AES_KEY aes_ks;
	FILE *infp = NULL;

	if((inPath == NULL) || (key == NULL))
	{
		return 1;
	}

	if((infp = fopen(inPath, "rb+")) == NULL)
	{
		return 2;
	}

	AES_set_decrypt_key(key, 128, &aes_ks);
	while(1)
	{
		len = fread(inData, 1, sizeof(inData),  (FILE*)infp);
		if(len <= 0)
		{
			break;
		}

		memset(outData,0,sizeof(outData));
		outLen = CRYPTO_cbc128_decrypt(inData, outData, len, &aes_ks, ivec,
							(block128_f) AES_decrypt);
		fseek(infp, (len*(-1)), SEEK_CUR);
		fwrite(outData, 1, outLen, infp);
	}
	fclose(infp);
	return 0;
}


